#include "GLIconRender.h"
#include "GLRenderComp.h"
#include "RenderController.h"
void GLIconRender::initVAO()
{
	if (mInited)
	{
		return;
	}
	mInited = true;

	mRenderDataIcon.mTexCoords = {
		QVector2D(0, 0),
		QVector2D(0, 1),
		QVector2D(1, 1),
		QVector2D(1, 0),
	};

	// 顶点坐标，存一个默认icon的坐标即可。
	// 默认坐标就取(0,0) (1,1),方便计算
	// Icon要实例化渲染，每个Icon图元配一个变换矩阵，通过默认坐标进行变换，得到最终坐标。
	// 这样实现，是OpenGL的实例化数组 标准用法。
	mRenderDataIcon.mVertices = {
		QVector3D(0.0f, 0.0f, 0.0),
		QVector3D(0.0f, 1.0f, 0.0),
		QVector3D(1.0f, 1.0f, 0.0),
		QVector3D(1.0f, 0.0f, 0.0),
	};
	mRenderDataIcon.mTexture = genTexture(":/img/position.png");

	// 生成VBO
	glGenBuffers(1, &mRenderDataIcon.mVerticesVBO);
	glGenBuffers(1, &mRenderDataIcon.mInstanceVBO);
	glGenBuffers(1, &mRenderDataIcon.mTexCoordsVBO);
	// 生成VAO
	glGenVertexArrays(1, &mRenderDataIcon.mVAO);

	// OpenGL各种Buffer的配置
	glBindVertexArray(mRenderDataIcon.mVAO);
	{
		const uint32_t vertexLocation	 = 0; // shader中 qt_Vertex 的索引号
		const uint32_t texCoordLocation	 = 1; // shader中 qt_MultiTexCoord0 的索引号
		const uint32_t instanceLocation1 = 2; // shader中 qt_InstanceMatrix 的索引号1。 mat4 要占4个。
		const uint32_t instanceLocation2 = 3; // shader中 qt_InstanceMatrix 的索引号2。 mat4 要占4个。
		const uint32_t instanceLocation3 = 4; // shader中 qt_InstanceMatrix 的索引号3。 mat4 要占4个。
		const uint32_t instanceLocation4 = 5; // shader中 qt_InstanceMatrix 的索引号4。 mat4 要占4个。
		// 顶点 Buffer的配置
		glBindBuffer(GL_ARRAY_BUFFER, mRenderDataIcon.mVerticesVBO);
		{
			glEnableVertexAttribArray(vertexLocation);
			glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(QVector3D), (void*)0);
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		glBindBuffer(GL_ARRAY_BUFFER, mRenderDataIcon.mTexCoordsVBO);
		{
			glEnableVertexAttribArray(texCoordLocation);
			glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(QVector2D), (void*)0);
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		// 变换矩阵的配置
		glBindBuffer(GL_ARRAY_BUFFER, mRenderDataIcon.mInstanceVBO);
		{
			glEnableVertexAttribArray(instanceLocation1);
			glVertexAttribPointer(instanceLocation1, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)0);

			glEnableVertexAttribArray(instanceLocation2);
			glVertexAttribPointer(instanceLocation2, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)(sizeof(QVector4D)));

			glEnableVertexAttribArray(instanceLocation3);
			glVertexAttribPointer(instanceLocation3, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)(2 * sizeof(QVector4D)));

			glEnableVertexAttribArray(instanceLocation4);
			glVertexAttribPointer(instanceLocation4, 4, GL_FLOAT, GL_FALSE, sizeof(QMatrix4x4), (void*)(3 * sizeof(QVector4D)));
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		// 变换矩阵的实例化配置，一个图元更新一次，即一条线一个变换矩阵。
		glVertexAttribDivisor(instanceLocation1, 1);
		glVertexAttribDivisor(instanceLocation2, 1);
		glVertexAttribDivisor(instanceLocation3, 1);
		glVertexAttribDivisor(instanceLocation4, 1);
	}
	glBindVertexArray(0);
}
void GLIconRender::updateData()
{
	// 计算变换矩阵
	QVector3D startZero = mRenderDataIcon.mVertices.at(0);
	QVector3D stopZero	= mRenderDataIcon.mVertices.at(2);
	mRenderDataIcon.mInstanceMats.clear();
	for (auto comp : gController->comps())
	{
		// 当前Icon坐标
		const auto& vertices = comp->mIcon->getVertices();
		auto		startNow = vertices.at(0);
		auto		stopNow	 = vertices.at(2);
		// 第一个Icon变换到当前Icon，需要平移的距离
		QVector3D offset = startNow - startZero;
		// x轴缩放。 默认坐标宽度为1，
		qreal	   scaleX = (stopNow.x() - startNow.x()) / 1.0f;
		qreal	   scaleY = (stopNow.y() - startNow.y()) / 1.0f;
		QMatrix4x4 mat;

		mat.translate(offset);
		mat.scale(scaleX, scaleY);

		//		// 叠加一个整体变换的矩阵
		//		mat = comp->mIcon->compMat() * mat;

		mRenderDataIcon.mInstanceMats.append(mat);
	}
	// 顶点数据从内存传到GPU显存
	glBindBuffer(GL_ARRAY_BUFFER, mRenderDataIcon.mVerticesVBO);
	{
		glBufferData(GL_ARRAY_BUFFER, sizeof(QVector3D) * mRenderDataIcon.mVertices.size(), mRenderDataIcon.mVertices.constData(), GL_STATIC_DRAW);
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glBindBuffer(GL_ARRAY_BUFFER, mRenderDataIcon.mTexCoordsVBO);
	{
		glBufferData(GL_ARRAY_BUFFER, sizeof(QVector2D) * mRenderDataIcon.mTexCoords.size(), mRenderDataIcon.mTexCoords.constData(), GL_STATIC_DRAW);
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	// 矩阵数据从内存传到GPU显存
	glBindBuffer(GL_ARRAY_BUFFER, mRenderDataIcon.mInstanceVBO);
	{
		glBufferData(GL_ARRAY_BUFFER, sizeof(QMatrix4x4) * mRenderDataIcon.mInstanceMats.size(), mRenderDataIcon.mInstanceMats.constData(), GL_STATIC_DRAW);
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GLIconRender::paint(QOpenGLShaderProgram* program, const QMatrix4x4& mvpMat)
{
	if (!program->bind())
	{
		qWarning() << program->log();
		return;
	}
	glBindVertexArray(mRenderDataIcon.mVAO);
	{
		mRenderDataIcon.mTexture->bind();
		program->setUniformValue("qt_ModelViewProjectionMatrix", mvpMat);
		program->setUniformValue("qt_Texture0", 0);
		glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, mRenderDataIcon.mInstanceMats.size());
		mRenderDataIcon.mTexture->release();
	}
	glBindVertexArray(0);
}
